using System.Text;
using Microsoft.EntityFrameworkCore;
using System.Text.Json.Serialization;
using Mathmall.Administration.Data;
using System.Text.Encodings.Web;
using System.Text.Unicode;
using System.Text.Json;
using Mathmall.Administration.Authorization;
using Mathmall.Administration.Config;
using Mathmall.Administration.Filter;
using Mathmall.Administration.Mapper;
using Mathmall.Administration.Models;
using Mathmall.Administration.Option;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using ILoggerFactory = log4net.Repository.Hierarchy.ILoggerFactory;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddConfig(builder.Configuration).AddMyDependencyGroup();
// json序列化配置
builder.Services.AddControllers().AddJsonOptions(option =>
{
    // 忽略循环引用
    option.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
    option.JsonSerializerOptions.WriteIndented = true;
});
// 数据库配置
builder.Services.AddDbContext<AdministrationContext>(options =>
{
    options.UseLoggerFactory(LoggerFactory.Create(logBuilder => logBuilder.AddLog4Net("Config/log4net.Config")))
        .UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
// 跨域配置
builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(
        policy => { policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); });
});
// 添加identity
builder.Services.AddIdentityCore<User>(options =>
    {
        options.SignIn.RequireConfirmedAccount = false;
        options.SignIn.RequireConfirmedEmail = false;
        options.SignIn.RequireConfirmedPhoneNumber = false;
    })
    .AddRoles<IdentityRole<int>>()
    .AddEntityFrameworkStores<AdministrationContext>();
// 配置Jwt
builder.Services.Configure<JwtOption>(builder.Configuration.GetSection("JwtOption"));
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>
    {
        var jwtOption = builder.Configuration.GetSection("JwtOption").Get<JwtOption>();
        byte[] issuerSigningKey = Encoding.UTF8.GetBytes(jwtOption!.IssuerSigningKey);
        SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(issuerSigningKey);
        opt.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = symmetricSecurityKey
        };
    }
);
builder.Services.AddAuthorization();
// 为swagger添加token
builder.Services.AddSwaggerGen(c =>
{
    var scheme = new OpenApiSecurityScheme()
    {
        Description = "Authorization",
        Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Authorization" },
        Scheme = "oauth2", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey
    };
    c.AddSecurityDefinition("Authorization", scheme);
    var requirement = new OpenApiSecurityRequirement();
    requirement[scheme] = new List<string>();
    c.AddSecurityRequirement(requirement);
});
builder.Services.AddScoped<IAuthorizationHandler, OperationHandler>();
// 全局异常处理
builder.Services.AddMvc(option => option.Filters.Add<GlobalExceptionFilter>());

// log4net
builder.Logging.ClearProviders();
builder.Logging.AddLog4Net("Config/log4net.Config");

var app = builder.Build();

// Configure the HTTP request pipeline. https://localhost:7276/swagger/index.html
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseCors("cors");
app.MapSwagger().RequireAuthorization();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();